/* peq.reajs
 * 
 * Copyright (c) 2012, Michael Gruhn
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 * THIS SOFTWARE.
 */

/* Parametric EQ after [1].
 */
desc: Parametric EQ

slider1:12000<20,22000,0.001>Frequency (Hz)
slider2:0<-12,12,0.000001>Gain (dB)
slider3:1<0,40,0.0001>Q
slider5:0<-96,320,0.0001>drive
slider6:1<0,1,{digital,analog}>-Curve shape
slider7:0<0,1,{1/2 Gain, 3dB}>-Width at
slider9:5<0,7,{lowpass,highpass,bandpass,notch,allpass,peak,lowshelf,highshelf}>Selector
slider10:0<-96,320,0.0001>drive2
slider11:0<-96,320,0.0001>driveB
slider12:0<-96,320,0.0001>driveB2
slider13:-48<-96,96,0.0001>drive all
@init
function tanh(x)
     (
x = exp(2*x); 
(x - 1) / (x + 1);  //(ex - e-x)/(ex + e-x)
);
function atanh(x)
     (
       (1/2*log((1+x)/(1-x)));
     );

@slider
drive = pow(10,(slider5+slider13)/20);
drive2 = pow(10,(slider10+slider13)/20);
driveb = pow(10,(slider11+slider13)/20);
drive2b = pow(10,(slider12+slider13)/20);
invdrive = pow(10,(-196)/20);
A = pow(10,(slider2/40));
q=slider3;

 w0 = (2 * $pi * (slider1)) / srate;
        alpha = sin(w0) / (2 * q);
slider9 == 0 ? (
            b0 = (1.0 - cos(w0)) / 2;
            b1 = 1.0 - cos(w0);
            b2 = (1.0 - cos(w0)) / 2;
            a0 = 1.0 + alpha;
            a1 = -2* cos(w0);
            a2 = 1.0 - alpha;
        );
 slider9 == 1 ? (
            b0 = (1.0 + cos(w0)) / 2;
            b1 = -(1.0 + cos(w0));
            b2 = (1.0 + cos(w0)) / 2;
            a0 = 1.0 + alpha;
            a1 = -2 * cos(w0);
            a2 = 1.0 - alpha;
        );
    slider9 == 2 ? (
            b0 = alpha;
            b1 = 0.0;
            b2 = -alpha;
            a0 = 1.0 + alpha;
            a1 = -2 * cos(w0);
            a2 = 1.0 - alpha;
       );
slider9 == 3 ? (
            b0 = 1.0;
            b1 = -2 * cos(w0);
            b2 = 1.0;
            a0 = 1.0 + alpha;
            a1 = -2 * cos(w0);
            a2 = 1.0 - alpha;
        );
slider9 == 4 ? (
            b0 = 1.0 - alpha;
            b1 = -2 * cos(w0);
            b2 = 1.0 + alpha;
            a0 = 1.0 + alpha;
            a1 = -2 * cos(w0);
            a2 = 1.0 - alpha;
       );
slider9 == 5 ? (
            b0 = 1.0 + alpha * A;
            b1 = -2 * cos(w0);
            b2 = 1.0 - alpha * A;
            a0 = 1.0 + alpha / A;
            a1 = -2 * cos(w0);
            a2 = 1.0 - alpha / A;
       );
slider9 == 6 ? (
            b0 = A * (((A + 1.0) - (A - 1.0) * cos(w0)) + 2 * sqrt(A) * alpha);
            b1 = 2 * A * (A - 1.0 - (A + 1.0) * cos(w0));
            b2 = A * ((A + 1.0) - (A - 1.0) * cos(w0) - 2 * sqrt(A) * alpha);
            a0 = A + 1.0 + (A - 1.0) * cos(w0) + 2 * sqrt(A) * alpha;
            a1 = -2 * ((A - 1.0) + (A + 1.0) * cos(w0));
            a2 = (A + 1.0 + (A - 1.0) * cos(w0)) - 2 * sqrt(A) * alpha;
       );
 slider9 == 7 ? (
            b0 = A * (A + 1.0 + (A - 1.0) * cos(w0) + 2 * sqrt(A) * alpha);
            b1 = -2 * A * ((A - 1.0) + (A + 1.0) * cos(w0));
            b2 = A * ((A + 1.0 + (A - 1.0) * cos(w0)) - 2 * sqrt(A) * alpha);
            a0 = ((A + 1.0) - (A - 1.0) * cos(w0)) + 2 * sqrt(A) * alpha;
            a1 = 2 * (A - 1.0 - (A + 1.0) * cos(w0));
            a2 = (A + 1.0) - (A - 1.0) * cos(w0) - 2 * sqrt(A) * alpha;
        );
        c1 = b0 / a0;
        c2= b1 / a0;
        c3= b2 / a0;
        c4= a1 / a0;
        c5=a2 / a0;
redraw = 25;

@sample
x0=spl0;
phase=(sin(atan2(x1,x0)))/(2 * q);
y0 = c1*x0 + c2*x1 + c3*x2 - c4*y1 - c5*y2;
y0temp=y0-x0;
amt=((phase-alpha)/$pi)+0.5;
y0 >= 0 ? (
spl0 = y0* abs(phase-alpha)/$pi+((tanh(y0*drive)/drive)*(1-amt)+(tanh(y0*drive2)/drive2)*amt)*(1-abs(phase-alpha)/$pi);
) : (
spl0 = y0* abs(phase-alpha)/$pi+((tanh(y0*driveb)/driveb)*(1-amt)+(tanh(y0*drive2b)/drive2b)*amt)*(1-abs(phase-alpha)/$pi);
);
y2 = y1; y1 = y0; x2 = x1; x1 = x0;
x0r=spl1;
phase=(sin(atan2(x1r,x0r)))/(2 * q);
y0r = c1*x0r + c2*x1r + c3*x2r - c4*y1r - c5*y2r;
amt=((phase-alpha)/$pi)+0.5;
y0r >= 0 ? (
spl1 = y0r* abs(phase-alpha)/$pi+((tanh(y0r*drive)/drive)*(1-amt)+(tanh(y0r*drive2)/drive2)*amt)*(1-abs(phase-alpha)/$pi);
) : (
spl1 = y0r* abs(phase-alpha)/$pi+((tanh(y0r*driveb)/driveb)*(1-amt)+(tanh(y0r*drive2b)/drive2b)*amt)*(1-abs(phase-alpha)/$pi);
);
y2r = y1r; y1r = y0r; x2r = x1r; x1r = x0r;
//spl0=y0;
//spl1=y0r;
@gfx
(redraw+=1) > 25 ? (
redraw = 0;

gfx_r=gfx_g=gfx_b=0; gfx_a=1;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);

gfx_r=gfx_g=gfx_b=0.25; gfx_a=1;
gfx_y = 0; gfx_x = (log(20)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(30)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(40)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(50)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(60)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(70)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(80)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(90)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=gfx_g=gfx_b=0.5; gfx_a=1;
gfx_y = 0; gfx_x = (log(100)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=gfx_g=gfx_b=0.25; gfx_a=1;
gfx_y = 0; gfx_x = (log(200)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(300)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(400)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(500)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(600)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(700)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(800)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(900)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=gfx_g=gfx_b=0.5; gfx_a=1;
gfx_y = 0; gfx_x = (log(1000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_r=gfx_g=gfx_b=0.25; gfx_a=1;
gfx_y = 0; gfx_x = (log(2000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(3000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(4000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(5000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(6000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(7000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(8000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);
gfx_y = 0; gfx_x = (log(9000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=gfx_g=gfx_b=0.5; gfx_a=1;
gfx_y = 0; gfx_x = (log(10000)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=0.5; gfx_g=gfx_b=0; gfx_a=1;
gfx_y = 0; gfx_x = (log(srate/2)/log(10)-log(20)/log(10))/3*gfx_w; gfx_lineto(gfx_x, gfx_h, 0);

gfx_r=gfx_g=gfx_b=1; gfx_a=1;
gfx_x = 0; gfx_y = gfx_h - (0 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);

gfx_r=gfx_g=gfx_b=0.5; gfx_a=1;
gfx_x = 0; gfx_y = gfx_h - (6 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);
gfx_x = 0; gfx_y = gfx_h - (-6 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);

gfx_r=gfx_g=gfx_b=0.25; gfx_a=1;
gfx_x = 0; gfx_y = gfx_h - (3 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);
gfx_x = 0; gfx_y = gfx_h - (-3 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);
gfx_x = 0; gfx_y = gfx_h - (9 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);
gfx_x = 0; gfx_y = gfx_h - (-9 + 12)/24 * gfx_h; gfx_lineto(gfx_w,gfx_y,0);


g_x = 0;
gfx_x = 0;
gfx_y = gfx_h/2;
flag=0;
loop(gfx_w-1,
//  g_w = 2*$pi*(((g_x/gfx_w)^g_s*19980+20)/srate);
  tmp = 10^(g_x/gfx_w*3+log(20)/log(10));
  g_w = 2*$pi*tmp/srate;
  g_phi = 4*sin(g_w/2)^2;
  oldgdb=g_db;
  g_db = (10*log( (b0+b1+b2)^2 + ( b0*b2*g_phi - (b1*(b0+b2) + 4*b0*b2) )*g_phi )/log(10) - 10*log( (a0+a1+a2)^2 + ( a0*a2*g_phi - (a1*(a0+a2) + 4*a0*a2) )*g_phi )/log(10));
  //g_phi >= $pi ? flag=tmp;
  w0b = (2 * $pi * (tmp)) / srate;
          alphab = sin(w0b) / (2 * q);
          amtb=((alphab)/$pi)+0.5;
  
  g_db = (((tanh(g_db*drive2)))/drive2)*(1-amtb)+(((tanh(g_db*drive)))/drive)*amtb;
  g_y = gfx_h - (g_db + 3)/6 * gfx_h;
  
  gfx_r=0;gfx_g=1;gfx_b=0; gfx_a=1;
  
  gfx_lineto(g_x+1,g_y,0);
  
  gfx_x=g_x;
  gfx_y=g_y;
  g_x+=1;
);

);
